﻿using System.Collections.Generic;
using System.Linq;
using Irony.Parsing;

namespace LibraryGuard.Internals
{
	/// <summary>
	/// Special terminal for pure text.
	/// </summary>
	internal class PureTextTerminal
		: Terminal
	{
		private string[] Stops;

		public PureTextTerminal(string name)
			: base(name)
		{
			this.Priority = TerminalPriority.Low;
		}

		public override IList<string> GetFirsts()
		{
			return null;
		}

		public override void Init(GrammarData grammarData)
		{
			base.Init(grammarData);

			this.Stops = grammarData.AllTerms
				.Where(t => t.Flags.HasFlag(TermFlags.IsReservedWord))
				.Select(t => t.Name)
				.ToArray();
		}

		public override Token TryMatch(ParsingContext context, ISourceStream source)
		{
			var stopIndex = this.FindMatch(source.Text, source.Location.Position);
			if (stopIndex == source.Location.Position)
				return null;
			if (stopIndex < 0)
				stopIndex = source.Text.Length;
			source.PreviewPosition = stopIndex;
			return source.CreateToken(this.OutputTerminal);
		}

		private int FindMatch(string text, int start)
		{
			for (int i = start; i < text.Length; i++)
			{
				foreach (var stop in this.Stops)
				{
					if (this.CompareSubstring(text, i, stop))
						return i;
				}
			}
			return -1;
		}

		private bool CompareSubstring(string text, int start, string search)
		{
			if (text.Length - start < search.Length)
				return false;
			for (int i = 0; i < search.Length; i++)
			{
				if (text[start + i] != search[i])
					return false;
			}
			return true;
		}
	}
}
